
/*
 *
 * Copyright (c) 2020-2022, Java知识图谱 (http://www.altitude.xin).
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package xin.altitude.cms.common.util;

import xin.altitude.cms.common.model.KVModel;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * MapUtils工具类
 * 用以简化多个key值的map取值操作
 * 提供处理Map多key取值工具方法
 *
 * @author <a href="http://www.altitude.xin" target="_blank">Java知识图谱</a>
 * @author <a href="https://gitee.com/decsa/ucode-cms-vue" target="_blank">UCode CMS</a>
 * @author <a href="https://space.bilibili.com/1936685014" target="_blank">B站视频</a>
 * @since 2019/06/03 22:49
 **/
public class MapUtils {
    private MapUtils() {
    }

    /**
     * 批量取出Map中的值
     *
     * @param source map实例
     * @param keys   键的集合
     * @param <K>    key的泛型
     * @param <V>    value的泛型
     * @return value的泛型的集合
     */
    @SafeVarargs
    public static <K, V> List<V> getCollection(Map<K, V> source, K... keys) {
        Objects.requireNonNull(keys);
        return getCollection(source, Arrays.asList(keys));
    }

    /**
     * 批量取出Map中的值
     *
     * @param source map实例
     * @param keys   键的集合
     * @param <K>    key的泛型
     * @param <V>    value的泛型
     * @return value的泛型的集合
     */
    public static <K, V> List<V> getCollection(Map<K, V> source, Iterable<K> keys) {
        List<V> result = new ArrayList<>();
        if (source != null && !source.isEmpty() && keys != null) {
            keys.forEach(key -> Optional.ofNullable(source.get(key)).ifPresent(result::add));
        }
        return result;
    }

    /**
     * 批量取出Map中的值
     *
     * @param source     map实例
     * @param keys       键key集合
     * @param comparator 排序器
     * @param <K>        key的泛型
     * @param <V>        value的泛型
     * @return value的泛型的集合
     */
    public static <K, V> List<V> getCollection(Map<K, V> source, Iterable<K> keys, Comparator<V> comparator) {
        Objects.requireNonNull(comparator);
        List<V> result = getCollection(source, keys);
        result.sort(comparator);
        return result;
    }

    /**
     * 将Map转化成List
     *
     * @param source 原始Map实例
     * @param <K>    Key类型
     * @param <V>    Value类型
     * @return 返回KVModel类型集合
     */
    public static <K, V> List<KVModel<K, V>> mapToList(Map<K, V> source) {
        Objects.requireNonNull(source);
        List<KVModel<K, V>> result = source.entrySet().stream()
            .map(e -> new KVModel<>(e.getKey(), e.getValue()))
            .collect(Collectors.toList());
        return result;
    }


    /**
     * 讲Map中 value进行转换
     *
     * @param source      原始Map实例
     * @param valueAction value转换的行为
     * @param <K>         Key的类型
     * @param <V>         原始value的类型
     * @param <T>         目标value类型
     * @return 转换后的Map
     */
    public static <K, V, T> Map<K, T> transformMap(Map<K, V> source, Function<? super V, ? extends T> valueAction) {
        Objects.requireNonNull(source);
        Objects.requireNonNull(valueAction);
        Map<K, T> hashMap = new HashMap<>();
        for (Map.Entry<K, V> entry : source.entrySet()) {
            hashMap.put(entry.getKey(), EntityUtils.toObj(entry.getValue(), valueAction));
        }
        return hashMap;
    }
}
